package com.example.ass7;

import com.example.ass7.geometryprimitives.Line;
import com.example.ass7.geometryprimitives.Point;

/**
 * @author Meirav Ben Izhak
 */
public class Equation {
    // the object's members
    private final double a;
    private final double b;
    private final double c;

    /**
     * @param a
     *            a to set
     * @param b
     *            a to set
     * @param c
     *            a to set
     */

    public Equation(double a, double b, double c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    /**
     * @param l
     *            the line to build the equation for
     */
    public Equation(Line l) {
        this.a = this.calcA(l);
        this.b = this.calcB(l);
        this.c = this.calcC(l);
    }

    /**
     * @param l
     *            line to calculate a for
     * @return the value for a
     */

    public double calcA(Line l) {
        double aToReturn = l.end().getY() - l.start().getY();
        return aToReturn;
    }

    /**
     * @param l
     *            line to calculate b for
     * @return the value for b
     */

    public double calcB(Line l) {
        double bToReturn = l.start().getX() - l.end().getX();
        return bToReturn;
    }

    /**
     * @param l
     *            line to calculate c for
     * @return the value for c
     */
    public double calcC(Line l) {
        double aTemp = this.calcA(l);
        double bTemp = this.calcB(l);
        double x1 = l.start().getX();
        double y1 = l.start().getY();

        double cToReturn = aTemp * x1 + bTemp * y1;
        return cToReturn;
    }

    /**
     * @return a's value
     */
    public double getA() {
        double aToReturn = this.a;
        return aToReturn;
    }

    /**
     * @return b's value
     */
    public double getB() {
        double bToReturn = this.b;
        return bToReturn;
    }

    /**
     * @return c's value
     */
    public double getC() {
        double cToReturn = this.c;
        return cToReturn;
    }

    /**
     * @param eq
     *            receives an equation.
     * @return the determinant's value
     */
    public double getDet(Equation eq) {
        double a1 = this.getA();
        double a2 = eq.getA();
        double b1 = this.getB();
        double b2 = eq.getB();

        double det = a1 * b2 - a2 * b1;

        return det;
    }

    /**
     * @param eq
     *            the equation to calculate the value for
     * @return the multiplication it calculated
     */
    public double getBCMultiply(Equation eq) {
        double b1 = this.getB();
        double b2 = eq.getB();
        double c1 = this.getC();
        double c2 = eq.getC();

        double bcMultiply = b2 * c1 - b1 * c2;
        return bcMultiply;
    }

    /**
     * @param eq
     *            the equation to calculate the value for
     * @return the multiplication it calculated
     */
    public double getACMultiply(Equation eq) {
        double a1 = this.getA();
        double a2 = eq.getA();
        double c1 = this.getC();
        double c2 = eq.getC();

        double acMultiply = a1 * c2 - a2 * c1;
        return acMultiply;
    }

    /**
     * @param eq
     *            the equation of the line we're checking
     * @return intersection- the point where the 2 lines intersect
     */
    public Point getIntersection(Equation eq) {

        double det = this.getDet(eq);

        double acMul = this.getACMultiply(eq);
        double bcMul = this.getBCMultiply(eq);

        double x = bcMul / det;
        double y = acMul / det;

        Point intersection = new Point(x, y);
        return intersection;
    }

    /**
     * @param l
     *            line to check intersection with
     * @param intersect
     *            point where the lines intersect
     * @return true if the intersection is within the lines' segments, false if
     *         it's not.
     */

    public boolean isIntersectionInLine(Line l, Point intersect) {
        boolean intersectionIsOnLine = false;

        // checking if intersection is on line1
        double minX = Point.min(l.end().getX(), l.start().getX());
        double maxX = Point.max(l.end().getX(), l.start().getX());
        double minY = Point.min(l.end().getY(), l.start().getY());
        double maxY = Point.max(l.end().getY(), l.start().getY());

        boolean yBoarders = intersect.getY() < maxY && intersect.getY() > minY;
        boolean xBoarders = intersect.getX() < maxX && intersect.getX() < minX;

        if (yBoarders && xBoarders) {
            intersectionIsOnLine = true;
        }
        return intersectionIsOnLine;
    }
}
